<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>ES6的数据结构【Map】</title>
</head>
<body>
    <script>
        /* Map 对象就是简单的键值对。其中的键和值可以使任意值。【对象的键只能是字符串：{name:1, age:12} 】 */
        // 它也像 Set 数据结构一样，没有重复哦
        // 实例属性和方法：size、set、get、has、delete、clear
        // 遍历方法：keys()、values()、entries()、forEach()

        /* 可直接如下添加数据 */
        var map1 = new Map([['one',1], ['two', 2], ['three', 3]]);

        ///实例属性和方法
        // 1. set(key, value)方法：设置【键】名 key 对应的【键】值为 value，然后返回整个 Map 结构【有则更新】
        var map = new Map();
        map.set('one', 1);
        map.set('two', 2);
        map.set('three', 3);   
        /* 键的比较规则：NaN 是与NaN是相同的（虽然NaN !== NaN）,除此之外所有的值都根据'==='判断 */
        var map = new Map();
        map.set(Number('aa111'), 'isNaN');
        map.set(Number('bb222'), '也 是 NaN');
        map.get(NaN);    //'也 是 NaN' 没有重复，所以只输出后一个
        
        // 2. size方法：返回Map对象的键值对的数量
        let msize = map1.size // 3

        // 3. get(key)方法：get 方法读取 key 对应的【键值】，如果找不到 key，返回undefined
        map1.get('one'); //true
        map1.get('aaa'); //false

        // 4. has(key)方法：方法返回一个布尔值
        map1.has('one') // true
        map1.has('aaa') // false

        // 5. delete(key)：delete(key) 删除某个【键】，返回true。如果删除失败，返回false
        map.delete('one'); //true
        console.log(map); //{ "one" => 1, "two" => "123", "three" => "3"}
        map.delete('one'); //false

        // 6. clear方法：移除Map对象的所有键值对【没有返回值】
        console.log(map1.size); //3
        map.clear();
        console.log(map1.size); // 0

        /// 遍历方法
        // 1. map1.keys()：返回一个新的Iterator对象，它按插入顺序包含了Map对象中每个元素的【键名】
        map1.keys();    //MapIterator {1, 2, 3}

        // 2. map1.values()：返回一个新的Iterator对象，它按插入顺序包含了Map对象中每个元素的【键值】
        map1.keys();    //MapIterator {'one', 'two', 'three'}

        // 3. map1.entries()：返回一个新的Iterator对象，它按插入【顺序】包含了Map对象中每个元素的[key, value]数组。
        map;    //Map {1 => "one", 2 => "two", 3 => "three"}
        map.entries();
        map;    //Map {1 => "one", 2 => "two", 3 => "three"}

        // 4. forEach(callbackFn, thisArg)：每一个键值对会调用一次callbackFn 函数，提供 thisArg 参数的话【它将在每次回调函数中作为this值】
        map.forEach(function(value, key, mapObj) {
            console.log(value + '---' + key + '---' + mapObj); // one --- 1 --- [object Map]
            //value - Map对象里每一个键值对的值
            //key - Map对象里每一个键值对的键
            //mapObj - Map对象本身
            console.log(this); //this === window
        });

        map.forEach(function(value, key, mapObj) {
            console.log(value + '---' + key + '---' + mapObj);
            console.log(this);    //this === map
        }, map)

        /*
        一个对象通常都有自己的原型，所以一个对象总有一个"prototype"键。
        不过，ES5 可以使用var map = Object.create(null)来创建一个没有原型的对象

        一个对象的键只能是字符串或者Symbols【ES6 新创的数据类型】，但一个Map的键可以是任意值。

        你可以通过size属性很容易地得到一个Map的键值对个数，而对象的键值对个数只能手动确认。

        Map.length ==> 0
        Map.prototype 表示Map构造器的原型【允许添加属性从而应用与所有的Map对象】
        Map.prototype.constructor 返回创建给map实例的构造函数，默认是Map函数【function Map() { [native code] }】
        */
    </script>
</body>
</html>